#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
#endregion

namespace SkyBurner
{
    public class Camera
    {
        private Vector3 m_vPosition;
        private Vector3 m_vUp;
        private Vector3 m_vRight;
        private Vector3 m_vView;
        private Vector3 m_vLookAt;
        private float m_fFOV;
        private float m_fNearPlane;
        private float m_fFarPlane;
        private float m_fAspectRatio;

        #region Properties
        public Vector3 Position
        {
            get { return m_vPosition; }
            set { m_vPosition = value; }
        }

        public Vector3 Up
        {
            get { return m_vUp; }
            set { m_vUp = value; }
        }

        public Vector3 Right
        {
            get { return m_vRight; }
        }

        public Vector3 View
        {
            get { return m_vView; }
            set
            {
                m_vView = value;
                m_vView.Normalize();

                m_vRight = Vector3.Cross(m_vUp, m_vView);
                m_vRight.Normalize();

                m_vUp = Vector3.Cross(m_vView, m_vRight);
                m_vUp.Normalize();
            }
        }

        public Vector3 LookAt
        {
            get
            {
                m_vLookAt = m_vPosition + m_vView;
                return m_vLookAt;
            }
            set
            {
                m_vLookAt = value;
                View = m_vLookAt - m_vPosition;
            }
        }

        public float FOV
        {
            get { return m_fFOV; }
            set { m_fFOV = value; }
        }

        public float NearPlane
        {
            get { return m_fNearPlane; }
            set { m_fNearPlane = value; }
        }

        public float FarPlane
        {
            get { return m_fFarPlane; }
            set { m_fFarPlane = value; }
        }

        public float AspectRatio
        {
            get { return m_fAspectRatio; }
            set { m_fAspectRatio = value; }
        }
        #endregion

        public Camera(Game game)
       {
            m_vPosition = new Vector3(0.0f, 0.0f, 0.0f);
            m_vUp = new Vector3(0.0f, 1.0f, 0.0f);
            m_vView = new Vector3(0.0f, 0.0f, 1.0f);

            m_vRight = Vector3.Cross(m_vUp, m_vView);
            m_vRight.Normalize();

            m_fFOV = 90.0f;
            m_fNearPlane = 0.1f;
            m_fFarPlane = 1000.0f;
        }

        public void Rotate(float pRotation, Vector3 pAxis)
        {
            Matrix mxRotationMatrix = Matrix.CreateFromAxisAngle(pAxis, pRotation);

            m_vView = Vector3.Transform(m_vView, mxRotationMatrix);
            m_vView.Normalize();

            m_vRight = Vector3.Cross(m_vUp, m_vView);
            m_vRight.Normalize();

            m_vUp = Vector3.Cross(m_vView, m_vRight);
            m_vUp.Normalize();
        }

        public void MoveForeward(float fStep)
        {
            m_vPosition += m_vView * fStep;
        }

        public void MoveBackward(float fStep)
        {
            m_vPosition -= m_vView * fStep;
        }

        public void MoveRight(float fStep)
        {
            m_vPosition += m_vRight * fStep;
        }

        public void MoveLeft(float fStep)
        {
            m_vPosition -= m_vRight * fStep;
        }

        public void Set(float fPosX, float fPosY, float fPosZ)
        {
            m_vPosition.X = fPosX;
            m_vPosition.Y = fPosY;
            m_vPosition.Z = fPosZ;
        }

        public void Set(Vector3 vPos)
        {
            Set(vPos.X, vPos.Y, vPos.Z);
        }
    }
}
